﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Web;


namespace http服务
{
    /// <summary>
    /// 创建HTTP服务
    /// </summary>
    public class HttpServer
    {

        System.Net.HttpListener httpserver = new System.Net.HttpListener();

        public void Start(string url = "http://*:8090/")
        {

            //身份认证
            //httpserver.AuthenticationSchemes.

            
            //邦定所有IP
            if (url.ToLower().Contains( "localhost"))
            {
                Uri uri = new Uri(url);
                foreach (var ip in System.Net.Dns.GetHostAddresses(Environment.MachineName))
                {
                    if (ip.AddressFamily == AddressFamily.InterNetwork)
                    {
                        string lurl = string.Format("{0}://{1}:{2}/", uri.Scheme, ip, uri.Port);
                        //添加监听
                        httpserver.Prefixes.Add(lurl);
                        Console.WriteLine(string.Format("开始监听:{0}", lurl));
                    }


                }
            }
            httpserver.Prefixes.Add(url);

            httpserver.Start();
            Console.WriteLine(string.Format("开始监听:{0}", url));
            //使用5个TPL进行监听
            for (int i = 0; i < 5; i++)
            {
                //监听HTTP请求
                System.Threading.Tasks.Task.Factory.StartNew(Quest);
                //处理HTTP请求
                System.Threading.Tasks.Task.Factory.StartNew(CycleWebRequest);
            }

            System.Threading.Tasks.Task.Factory.StartNew(() =>
            {
                NumResponse();
            });
             

        }


        /// <summary>
        /// 获取HTTP请求的委托,用于外部调用处理
        /// </summary>
        public Action<HttpListenerContext> HttpRequestAction;


        public void Stop()
        {
            httpserver.Stop();
        }

        /// <summary>
        /// 获取HTTP请求
        /// </summary>
        private void Quest()
        {

            while (httpserver.IsListening)
            {
                GetQuerst();
            }

        }

        /// <summary>
        /// htttp请求队列
        /// </summary>
        protected System.Collections.Concurrent.ConcurrentQueue<HttpListenerContext> RequestQueue = new System.Collections.Concurrent.ConcurrentQueue<HttpListenerContext>();

        /// <summary>
        /// 请求总数
        /// </summary>
        protected long RequestCount = 0;



        /// <summary>
        /// 获取一个请求
        /// </summary>
        protected void GetQuerst()
        {
            try
            {
                Task<HttpListenerContext> d = httpserver.GetContextAsync();
                RequestQueue.Enqueue(d.Result);
                System.Threading.Interlocked.Add(ref RequestCount, 1);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }


        /// <summary>
        /// 提供对基于自旋的等待的支持
        /// </summary>
        protected System.Threading.SpinWait spin = new System.Threading.SpinWait();


        /// <summary>
        /// 循环处理
        /// </summary>
        protected void CycleWebRequest()
        {
            while (httpserver.IsListening || RequestQueue.Count > 0)
            {
                DoProcessWebRequest();
            }
        }

        /// <summary>
        /// 处理HTTP请求
        /// </summary>
        protected void DoProcessWebRequest()
        {
            HttpListenerContext context;
            if (RequestQueue.TryDequeue(out context))
            {
                if (context != null)
                {
                    //调用外部处理方法
                    if (HttpRequestAction != null)
                    {
                        HttpRequestAction(context);
                    }
                

                    HttpListenerRequest request = context.Request;
                    HttpListenerResponse response = context.Response;
                    string ep = request.RemoteEndPoint.ToString();
                    #region 输出
                    try
                    {

                        Console.WriteLine("新请求接入:{0}", ep);
                      //键	值Server	Microsoft-HTTPAPI/2.0
                        response.Headers.Remove("Server");
                        //设置头
                        response.Headers.Add("WebServer", "InCom.API HTTP Server/1.0");
                        string responseString = string.Format("<HTML><BODY> {0}</BODY></HTML>", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"));
                        byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
                        //对客户端输出相应信息.
                        response.ContentLength64 = buffer.Length;
                        System.IO.Stream output = response.OutputStream;
                        output.Write(buffer, 0, buffer.Length);
                        //关闭输出流，释放相应资源
                        output.Close();
                        output.Dispose();
                    }
                    catch (System.Net.HttpListenerException ex) { Console.WriteLine( "远程节点:{0}, 处理请求异常:{1}",ep,ex); }
                    finally
                    {
                        response.Close();
                        System.Threading.Interlocked.Add(ref CountNumber, 1);
                    }

                    #endregion

                }
            }
            else
            {
                //我们可以把 Thread.Sleep(1) 可以换成 SpinWait.SpinUntil(() => false, 1);
                //停止一个时间片
                //System.Threading.Thread.Sleep(1);
                //等待时间为1毫秒
                //System.Threading.SpinWait.SpinUntil(() => false, 1);
                spin.SpinOnce();
            }
        }


        #region 获取CPU核心个数
        //        再在代码中  using System.Management;
        //以下是获取CPU属性的代码
        //            // Get the WMI class
        //            ManagementClass c = new ManagementClass(
        //            new ManagementPath("Win32_Processor"));
        //            // Get the properties in the class
        //            ManagementObjectCollection moc = c.GetInstances();

        //            // display the properties
        //            richTextBox1.Text += "\r";
        //            richTextBox1.Text += "Property Names: " + "\r";
        //            richTextBox1.Text += "=================" + "\r";
        //            foreach (ManagementObject mo in moc)
        //            {
        //                PropertyDataCollection properties = mo.Properties;
        ////获取内核数代码
        //                richTextBox1.Text += "物理内核数:"+ properties["NumberOfCores"].Value +"\r";
        //                richTextBox1.Text += "逻辑内核数:"+ properties["NumberOfLogicalProcessors"].Value+"\r";
        ////其他属性获取代码
        //                foreach (PropertyData property in properties)
        //                {
        //                    richTextBox1.Text += property.Name + ":" + property.Value + "\r";
        //                }
        //            }
        #endregion

        #region 记数器

        /// <summary>
        /// 记数器开始时间
        /// </summary>
        internal static DateTime StartTime = DateTime.Now.AddHours(1);
        /// <summary>
        /// 记数
        /// </summary>
        internal static long CountNumber = 0;

        /// <summary>
        /// 记数器输出
        /// </summary>
        internal static void NumResponse()
        {

            double ss = (DateTime.Now - StartTime).TotalSeconds;
            long num = CountNumber;

            StartTime = DateTime.Now;
            System.Threading.Interlocked.Exchange(ref CountNumber, 0);
            if (num > 0)
            {
                string xstr = string.Format("处理速度{0}/s", (num / ss).ToString("f2"));
                Console.WriteLine(xstr);
                System.Diagnostics.Trace.WriteLine(xstr);
            }

            System.Threading.Thread.Sleep(10 * 1000);

            NumResponse();
        }


  

        #endregion

    }


  
 
}